package com.xyy.saas.payment.adpater.xydLoan.support;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.adpater.xydLoan.core.constants.XydCreditLoanConstants;
import com.xyy.saas.payment.adpater.xydLoan.core.resp.XydLoanResponse;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.trace.AlarmService;
import com.xyy.saas.payment.util.xydSign.XydSignUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author wangzeqi
 */
@Slf4j
@Component
public class XydLoanClient {

    @Value("${xydLoad.client.urlPrefix:https://zeus-gateway.test-xyd40-1.xiaoyudian.com/open-platform-pre}")
    private String urlPrefix;
    @Value("${xydLoad.client.accessKey:b2d5bd71cf4ae7d43bdcfa702a4612d9}")
    private String accessKey;
    @Value("${xydLoad.client.timeoutMills:5000}")
    private int timeout;
    @Value("${xydLoad.client.response.publicKey:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDItppjWYJv5P697aanHJB4V/ttOiZybWW6zCUKQ10Py9ZS3w1CdylGFdCIvup9sXOvwnZ/IRuIzSY54thXxqeCeDAWmlwNoHQTMOeHYkS1LbikEgwbj20WKq3vyX5FkZ2/hRMjAmNwm327FxG94x5RxzmDSg4r1dn980ax20enJwIDAQAB}")
    private String XYD_RESPONSE_PUBLIC_KEY;
    @Value("${xydLoad.client.request.privateKey:MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+sNjsGUCwu3tE42ZTsTfMkPYlZCspv7mlXoxcjbMYD6T9OO6iN7XHmT+PHJ1W5wC8fRxAO1T7lZbx1bnKFx68GDX74RaVkv1Zce8RJ+Fk4oWXEj4T5pyAJHNicd0EwNMJuFJTK5FiYhpK2FSihrVRieI5pIpezadu3zaL8wYzNAgMBAAECgYAD6lOIBEIHEjfsR7pWPqJZL/GlXpHWtnou0L6XENYUB2NB4GXr0AJaikY/FNxTj75XCmkrXNwe3K2LF0AtSswIRDmyKZfekl1wWJyJLnz71UZV07leTpdvvw8BIvhhEY8oWGPnSLO+XfaFkdlP+qGevmzaRJS4icpKEpWM4ZfnQQJBAPh/mYvpW6CpyewH1jwhMZN6yEjei8PodFl07vkyy0Gihtm8v7WPC0ZewwiDGxeZUHoh7B4bfXqz4AppmjzjskkCQQCUAoRXtyPkMK5CdWSXIjepbUQIRuZLkZ1IDxZc0KOFnbagomoRLCeFoSQxmdFYioBRUalBI5wC+/OGdQZKyoZlAkBeVpLEOuM+KzctFAyQ50ka5BIFF/eXeDgzfeD7Wf0v/bOUFcPx+Uweevsv0BYI73tN4nLxOx535rG3Qj/7vbWBAkEAh4FGaIfi9CcdYvrW/Qb2rsa6YlmGveiydiZZ8t+Q1eNuL+KB+PbTuCOvXznTz5v9nnWE334adyDz80VwXUjNgQJALgmszP2gpP9/ju9rEjBDJLcbWS6Z/sfMcW6LmbVdgNsLNdrNb+RC6QTazyJQj6wHjHMDRC3lpoILqVgpd0e2Pw==}")
    private String XYD_REQUEST_PRIVATE_KEY;

    // private static final String urlPrefix = ApolloUtil.getProperty("xydLoad.client.urlPrefix", "https://zeus-gateway.test-xyd40-1.xiaoyudian.com/open-platform-pre");
    // private static final String accessKey = ApolloUtil.getProperty("xydLoad.client.accessKey", "b2d5bd71cf4ae7d43bdcfa702a4612d9");
    // private static final int timeout = ApolloUtil.getIntegerProperty("xydLoad.client.timeoutMills", 5000);

    //private static final String XYD_RESPONSE_PUBLIC_KEY = ApolloUtil.getProperty("xydLoad.client.response.publicKey", XydCreditLoanConstants.XYD_TEST_PUBLIC_KEY);
    //private static final String XYD_REQUEST_PRIVATE_KEY = ApolloUtil.getProperty("xydLoad.client.request.privateKey", XydCreditLoanConstants.B2B_TEST_PRIVATE_KEY);

    private final AlarmService alarmService;

    public XydLoanClient(AlarmService alarmService) {
        this.alarmService = alarmService;
    }

    public <T> T execute(String logScene, String url, String jsonParam, Class<T> rClazz) throws PaymentException {

        url = urlPrefix + url;

        Map<String, String> headers = creatRequestHeaders(jsonParam);

        try (HttpResponse httpResponse = HttpUtil.createPost(url)
                .timeout(timeout)
                .addHeaders(headers)
                .body(jsonParam)
                .execute()) {

            String response = httpResponse.body();
            log.info("{} XydLoanClient execute response:{}, url:{}, jsonParam:{}", logScene, response, url, jsonParam);

            // 验签
            boolean verifySuc = XydSignUtil.verifySign(response, XYD_RESPONSE_PUBLIC_KEY);
            if (!verifySuc) {
                log.error("{} XydLoanClient execute response verifySign fail. url:{}, jsonParam:{}", logScene, url, jsonParam);
                throw new PaymentException(ResultCodeEnum.XYDLOAN_SIGN_VERIFY_FAIL);
            }

            XydLoanResponse xydLoanResponse = JSON.parseObject(response, XydLoanResponse.class);
            return parseXydLoanResponse(xydLoanResponse, rClazz);

        } catch (Exception e) {
            log.error("{} XydLoanClient execute error. url:{}, jsonParam:{}", logScene, url, jsonParam, e);

            if (e instanceof PaymentException) {
                throw e;
            }

            alarmService.asyncAlarm("支付中台调小雨点接口异常", "XydLoanClient.execute",
                    logScene + "失败原因：" + e.getMessage(), jsonParam);

            throw new PaymentException(ResultCodeEnum.XYDLOAN_CLIENT_ERROR);
        }
    }

    private <T> T parseXydLoanResponse(XydLoanResponse xydLoanResponse, Class<T> rClazz) throws PaymentException {
        if (xydLoanResponse == null) {
            throw new PaymentException(ResultCodeEnum.XYDLOAN_RESPONSE_ERROR);
        }

        if (!XydCreditLoanConstants.SUCCESS_CODE.equals(xydLoanResponse.getCode())) {
            String errorMsg = xydLoanResponse.getMessage();
            throw new PaymentException(ResultCodeEnum.XYDLOAN_RESPONSE_ERROR, StringUtils.isNotBlank(errorMsg) ? errorMsg : ResultCodeEnum.XYDLOAN_RESPONSE_ERROR.getDisplayMsg());
        }

        Object data = xydLoanResponse.getData();
        if (data == null) {
            return null;
        }

        if (rClazz == null) {
            return null;
        }
        return JSON.parseObject(data + "", rClazz);
    }

    @SneakyThrows
    private Map<String, String> creatRequestHeaders(String jsonString) {
        String currentTimeStr = String.valueOf(System.currentTimeMillis());

        Map<String, String> headers = new HashMap<>();
        headers.put(XydCreditLoanConstants.HEADER_ACCESSKEY, accessKey);
        headers.put(XydCreditLoanConstants.HEADER_SIGN, XydSignUtil.sign(jsonString, currentTimeStr, XYD_REQUEST_PRIVATE_KEY));
        headers.put(XydCreditLoanConstants.HEADER_TIMESTAMP, currentTimeStr);
        return headers;
    }

}
